package com.guosen.zebra.framework.starter.etcd.client;

import com.guosen.zebra.framework.starter.etcd.properties.EtcdDiscoveryProperties;
import com.guosen.zebra.framework.starter.etcd.registry.EtcdServiceInstance;
import com.guosen.zebra.framework.starter.etcd.util.EtcdClientUtil;
import com.guosen.zebra.framework.starter.etcd.util.JsonParser;
import io.etcd.jetcd.Client;
import io.etcd.jetcd.KeyValue;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.util.CollectionUtils;

import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class EtcdDiscoveryClient implements DiscoveryClient {

    private EtcdDiscoveryProperties etcdDiscoveryProperties;

    public EtcdDiscoveryClient(EtcdDiscoveryProperties etcdDiscoveryProperties) {
        this.etcdDiscoveryProperties = etcdDiscoveryProperties;
    }

    @Override
    public String description() {
        return "Spring Cloud Etcd Discovery Client";
    }

    @Override
    public List<ServiceInstance> getInstances(String serviceId) {

        Client client = etcdDiscoveryProperties.getClient();
        String prefix = etcdDiscoveryProperties.getDiscoveryPrefix();
        String group = etcdDiscoveryProperties.getGroup();

        String path = prefix + "/" + group + "/" + serviceId;

        List<KeyValue> kvs = EtcdClientUtil.getByPrefix(client, path, etcdDiscoveryProperties.getTtl());
        if (CollectionUtils.isEmpty(kvs)) {
            return Collections.emptyList();
        }

        return kvs.stream()
                .map(keyValue -> toServiceInstance(serviceId, keyValue))
                .collect(Collectors.toList());
    }

    @Override
    public List<String> getServices() {
        Client client = etcdDiscoveryProperties.getClient();
        String prefix = etcdDiscoveryProperties.getDiscoveryPrefix();
        String group = etcdDiscoveryProperties.getGroup();
        String serviceIdPrefix = prefix + "/" + group;

        List<KeyValue> kvs = EtcdClientUtil.getByPrefix(client, serviceIdPrefix, etcdDiscoveryProperties.getTtl());
        if (CollectionUtils.isEmpty(kvs)) {
            return Collections.emptyList();
        }

        return kvs.stream()
                .map(KeyValue::getKey)
                .map(k -> new String(k.getBytes(), StandardCharsets.UTF_8))
                .collect(Collectors.toList());
    }

    private ServiceInstance toServiceInstance(String serviceId, KeyValue keyValue) {
        String valueStr = new String(keyValue.getValue().getBytes(), StandardCharsets.UTF_8);
        return JsonParser.toObject(valueStr, EtcdServiceInstance.class);
    }
}
